﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NuSoft.ExpressionEditor.Common.Interfaces;

namespace NuSoft.ExpressionEditor.ExampleParser.Tests
{
    [TestFixture]
    public class MathParserTests
    {

        MathParser parser = new MathParser();
        [TestCase]
        public void AssertLeftToRightOrderPreserved()
        {


            string expr = "2 - 2 -2";
            int expected = -2;
            Nemerle.Core.option<int> res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);

            expr = "8/2/2";
            expected = 2;
            res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);
        }

        [TestCase]
        public void AssertAtomicExpressionsWork()
        {
            string expr = "12435";
            int expected = 12435;
            Nemerle.Core.option<int> res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);

            expr = "-4665";
            expected = -4665;
            res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);

            expr = "(3565565)";
            expected = 3565565;
            res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);
        }

        [TestCase]
        public void AssertOpertaionsPriorityPreserved()
        {
            string expr = "2+2*2";
            int expected = 6;
            Nemerle.Core.option<int> res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);

            expr = "2*2+2";
            expected = 6;
            res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);

            expr = "2*(2+2)";
            expected = 8;
            res = parser.Parse(expr);
            Assert.IsTrue(res.HasValue);
            Assert.AreEqual(expected, res.Value);
        }

        [TestCase]
        public void AssertComplexExpressionsWork()
        {

            DummyTestObj obj = new DummyTestObj() { Prop1 = 2, Prop2 = 4 };
            string expr = "-(-(10    +Abs(-$Prop1) - Abs(3)- $Prop2 *$Prop2 / $Prop1/   $Prop1  + ($Prop1+6)/$Prop1  +(-1)))";
            int expected = 8;
            IParsingResult res = parser.Parse(obj,expr);
            Assert.IsFalse(res.HasError);
            Assert.AreEqual(expected, res.Result);

            for (int i = 0; i < 10; i++)
            {
                expr = String.Format("({0}) + ({0}) -(Abs(-({0}))) + ({0})", expr);
                expected *= 2;
                res = parser.Parse(obj,expr);
                Assert.IsFalse(res.HasError);
                Assert.AreEqual(expected, res.Result);
            }
            
        }
    }

    class DummyTestObj{
        public int Prop1 { get; set; }
        public int Prop2 { get; set; }
    }
}
